创建 Kanzi Studio 命令插件

Kanzi Studio 插件扩展 Kanzi Studio 的功能并在 Kanzi Studio 中运行。 使用 Kanzi Studio 插件:

您可以在包含Kanzi Studio 插件用户界面的 Kanzi Studio 窗口中呈现插件,也可以将其作为用户可以从上下文菜单中执行的命令,在没有用户界面的情况下运行插件。本主题介绍如何创建 Kanzi Studio 命令插件。要了解如何创建 Kanzi Studio 窗口插件,请参阅 创建 Kanzi Studio 窗口插件

Kanzi Studio 插件接口作为 .NET 框架程序集提供。您可以在 <KanziInstallation>/Studio/Bin/PluginInterface.dll 中找到它。插件接口可用于访问Kanzi Studio 中的数据和命令。When you want to use a Kanzi Studio plugin with different versions of Kanzi Studio, build the plugin with the PluginInterface.dll from each version of Kanzi Studio where you want to use that plugin.

要开发 Kanzi Studio 命令插件,请执行以下操作:

  1. 创建 Kanzi Studio 插件的基项。请参阅 创建 Kanzi Studio 命令插件的基项
  2. 构建和运行 Kanzi Studio 插件。请参阅 构建和运行 Kanzi Studio 插件
  3. Kanzi Studio 插件添加功能。请参阅 向 Kanzi Studio 命令插件添加功能向 Kanzi Studio 命令插件添加多个命令
  4. 调试 Kanzi Studio 插件。请参阅 调试 Kanzi Studio 插件

要查找有关 Kanzi Studio 插件接口的详细信息,请参阅:

创建 Kanzi Studio 命令插件的基项

Kanzi Studio 命令插件是作为单个命令执行的插件,没有用户界面。例如,使用命令插件在工程的整个场景图或选定的场景图部分执行命令。

您可在这里创建 Kanzi Studio 命令插件的基项,然后向其中添加功能来扩展 Kanzi Studio 的功能。

要创建 Kanzi Studio 命令插件:

  1. 在 Visual Studio 中选择文件 (File) > 新建(New) > 工程 (Project),并创建 Visual C# 类库。
  2. 在 Solution Explorer 中,右键点击工程名称,选择添加 (Add) > 参考 (Reference),然后向文件添加参考:
    1. 选择程序集 (Assemblies) > 框架 (Framework),定位 .NET 框架 (NET Framework),然后将参考添加到: System.ComponentModel.Composition
    2. 点击浏览 (Browse...),并将参考添加到 <KanziInstallation>/Studio/Bin/PluginInterface.dll 文件。
  3. 在 Solution Explorer 中,右键点击工程名称,选择属性 (Properties),并:

  4. 打开 Class1.cs 文件,并为 System.ComponentModel.CompositionKanzi Studio 插件接口添加 using 指令:
    using System.ComponentModel.Composition;
    using Rightware.Kanzi.Studio.PluginInterface;
  5. 定义在其中实现 PluginCommand 界面的命令类之前,使用导出特性告诉 Kanzi Studio .dll 是一个插件。在本示例中,您在 Class1 类中实现该插件命令。
    [Export(typeof(PluginContent))]
  6. 设置 Class1 用于实现 PluginCommand 界面的类,在 Class1 类中实现该界面。Kanzi 使用该类来创建此插件命令。
    1. 更改
      public class Class1

      public class Class1 : PluginCommand
    2. 实现 PluginCommand 界面。
      例如,将鼠标悬停在 PluginCommand, 上,点击 ,然后选择实现界面 (Implement Interface)。
  7. 在所有函数中,使用您要执行的代码替换这一行:
    throw new NotImplementedException();

    确保插件处理所有内部异常,不让它们传递到 Kanzi Studio 界面。

    例如,设置 Class1 类中的函数:
  8. 构建和运行插件。请参阅构建和运行 Kanzi Studio 插件

此处您创建了 Kanzi Studio 插件的基本结构,仅向 Kanzi Studio 日志 (Log) 窗口打印一条消息。要让插件进行更多操作,将您要让插件运行的代码添加到 Execute 函数。请参阅 向 Kanzi Studio 命令插件添加功能向 Kanzi Studio 命令插件添加多个命令

要进一步开发您的 Kanzi Studio 插件,请参阅 Kanzi Studio 插件接口概览Kanzi Studio 插件接口 API 参考

构建和运行 Kanzi Studio 插件

要构建和运行 Kanzi Studio 插件:

  1. 在 Visual Studio 中选择构建 (Build) > 构建解决方案 (Build Solution) 来构建插件 .dll。
  2. Kanzi Studio 插件 .dll 复制到 %ProgramData%\Rightware\<KanziVersion>\plugins 目录。
    如果 plugins 目录在 %ProgramData%\Rightware\<KanziVersion> 中不存在,请创建。

    建议

    In Windows Explorer create a shortcut from your Kanzi Studio plugin dll file and move the shortcut to the %ProgramData%\Rightware\<KanziVersion>\plugins directory.
    When you build the plugin, you can see in the Output window the location where Visual Studio stored the plugin dll file.

  3. 打开 Kanzi Studio
    Kanzi Studio 加载插件并将它们添加到从节点和资源调用的主菜单或上下文菜单中。
  4. Kanzi Studio 中选择插件主菜单并选择插件,或右键点击工程 (Project) 中的节点并选择插件的名称来运行插件。

Kanzi Studio 命令插件添加功能

Kanzi Studio 命令插件创建基项后,向您的插件添加功能,以使其发挥作用。请创建一个插件,删除所有没有子节点的 空节点 (Empty Node) 节点。

要使用 Kanzi Studio 插件删除没有子节点的空节点 (Empty Node) 节点:

  1. 创建 Kanzi Studio 命令插件的基项。请参阅 创建 Kanzi Studio 命令插件的基项
  2. 在 Visual Studio 中,打开插件的 Visual Studio 解决方案,然后打开实现 PluginCommand 界面的类库文件。
  3. Execute 函数中,编写当您调用插件命令时插件执行的代码。
    例如,要创建会删除没有子节点的所有 空节点 (Empty Node) 节点,请向 Execute 函数添加:
    //插件执行此函数内容。将插件代码置于此处。
    public void Execute(PluginCommandParameter parameter)
    {
        var items = parameter.Items;
        //打印到 Kanzi Studio 日志 (Log) 窗口。
        studio.Log("Deleting all 空节点 (Empty Node) nodes without child nodes");
    
        //从主菜单执行时,项传递空值作为参数。
        //从上下文菜单执行时,项传递选定项作为参数
        //(即使选择了多个项亦是如此)。
        if (items != null && items.Any())
        {
            // 如果从上下文菜单执行,启动从
            //执行节点遍历场景图的函数。
            TraverseTree(items);
        }
        else
        {
            //检查打开的工程。
            if (studio != null && studio.ActiveProject!= null && studio.ActiveProject.Screen != null)
            {
                //如果从主菜单执行,启动
                //从屏幕 (Screen) 节点的第一个子节点遍历场景图的函数。
                TraverseTree(studio.ActiveProject.Screen.Children);
            }
        }
    }
    
    // TraverseTree 函数从启动插件的节点开始遍历场景图。
    private void TraverseTree(IEnumerable<ProjectItem> items)
    {
        foreach (var item in items.ToArray())
        {
            //如果节点为 2D 空节点 (Empty Node 2D)3D 空节点 (Empty Node 3D) 并且没有
            //任何子节点,则将其删除。
            if ((item is EmptyNode2D || item is EmptyNode) && !item.Children.Any())
            {
                //删除使用命令的工程项。这可让您
                //撤销插件执行的动作。
                studio.Commands.DeleteProjectItem(new ProjectItem[] { item });
            }
            //遍历当前节点的子节点。
            else if (item.Children.Any())
            {
                TraverseTree(item.Children);
            }
        }
    }
  4. CanExecute 函数中,设置在 Kanzi Studio 中调用此插件命令的方式和位置。
    public bool CanExecute(PluginCommandParameter parameter)
    {
        //只有选择了场景图中的单个节点时,才允许
        //运行此插件命令。从主菜单执行插件时,调用零项,
        //该操作将插件设置为开始从
        //屏幕 (Screen) 节点的第一个子节点遍历场景图。
        var items = parameter.Items;
        return items != null && items.Count() <= 1;
    }
  5. Kanzi Studio 中,创建包含多个空节点 (Empty Node) 节点的工程,有些节点有子节点,有些没有子节点。
  6. 构建和运行插件。请参阅构建和运行 Kanzi Studio 插件
    执行此命令,将移除没有任何子节点的 空节点 (Empty Node) 节点,具体取决于您调用该插件命令的位置:

要进一步开发您的 Kanzi Studio 插件,请参阅 Kanzi Studio 插件接口概览Kanzi Studio 插件接口 API 参考

Kanzi Studio 命令插件添加多个命令

Kanzi Studio 命令插件创建基项后,向您的插件添加功能。您可以创建一个 Kanzi Studio 命令插件,实现多个命令。请创建一个包含以下命令的插件:

该插件查找并移除活动工程中,指向同一工程中或已加载的引用工程中资源的无效 kzb URL。

记录无效 kzb URL

要记录 Kanzi Studio 工程中的无效 kzb URL,请执行以下操作:

  1. 创建 Kanzi Studio 命令插件的基项。请参阅 创建 Kanzi Studio 命令插件的基项
    例如,创建一个名为“InvalidKzbUrlFinder”的 Visual Studio 工程,具有一个名为 ListInvalidKzbUrls 的类,该类可实现 PluginCommand 界面 :
    using System.ComponentModel.Composition;
    using Rightware.Kanzi.Studio.PluginInterface;
    
    namespace InvalidKzbUrlFinder
    {
        [Export(typeof(PluginContent))]
        public class ListInvalidKzbUrls : PluginCommand
        {
            private KanziStudio studio;
    
            public void Initialize(KanziStudio studio)
            {
                this.studio = studio;
            }
    
            //在 Kanzi Studio 主菜单中,显示名为“Kzb URL 检查器”的插件命令。
            public CommandPlacement CommandPlacement =>
                new CommandPlacement("Kzb URL Checker", ContextMenuPlacement.NONE, false, null);
    
            //设置该插件命令的内部名称。此函数使您无需额外更改插件,即可更改命令的显示名称。
            public string Name => "LogInvalidKzbUrls";
    
            //设置 Kanzi Studio 主菜单中的命令名。
            public string DisplayName => "Log Invalid Kzb URLs";
    
            //设置命令的工具提示。
            public string Description => "Prints to the 日志 (Log) the invalid kzb URLs in the active project.";
    
            public bool CanExecute(PluginCommandParameter parameter)
            {
                return studio?.ActiveProject != null;
            }
        }
    }
  2. 在实现 PluginCommand 界面的类中,添加从资源的 kzb URL 获取包含该资源的工程名称的函数。
            public static Project GetProjectFromKzbUrl(Solution solution, string urlCandidate)
            {
                Project result = null;
                foreach (var project in solution.Projects)
                {
                    var projectName = project.Name.Replace(" ", "_").ToLowerInvariant();
                    if (urlCandidate?.StartsWith("kzb://" + projectName) == true)
                    {
                        result = project;
                        break;
                    }
                }
    
                return result;
            }
    
            public Project GetProjectFromKzbUrl(string urlCandidate)
            {
                return GetProjectFromKzbUrl(studio.Solution, urlCandidate);
            }
    
  3. System.Linq 命名空间添加使用指令。
    您在下一步中添加的函数使用 LINQ Enumerable.Where 方法。
    using System.Linq;
  4. 在实现 PluginCommand 界面的类中,添加一个函数检查 kzb URL 是否指向现有资源。
            public static bool IsValidKzbUrl(Solution solution, Project project, string kzbUrl)
            {
                var result = false;
                if (GetProjectFromKzbUrl(solution, kzbUrl) == project)
                {
                    var projectNameInKzbFormat = project.Name.Replace(" ", "_").ToLowerInvariant();
                    var itemPath = kzbUrl.Substring(("kzb://" + projectNameInKzbFormat + "/").Length);
                    ProjectItem currentItem = project;
    
                    var parts = itemPath.Split('/').Where(x => !string.IsNullOrEmpty(x));
                    foreach (var part in parts)
                    {
                        currentItem = currentItem.GetChild(part);
                        if (currentItem == null)
                        {
                            break;
                        }
                    }
    
                    result = currentItem != null;
                }
    
                return result;
            }
  5. 在实现 PluginCommand 界面的类中,添加一个函数,打印无效 kzb URL 到 日志 (Log)
            private int LogKzbUrls(ProjectItem item, int count)
            {
                foreach (var projectItem in item.Children)
                {
                    var properties = projectItem.Properties;
                    foreach (var property in properties)
                    {
                        var propertyValue = projectItem.Get(property);
                        var nodeResource = propertyValue as ResourceReferenceBase;
                        if (nodeResource != null)
                        {
                            var project = GetProjectFromKzbUrl(nodeResource.ResourceID);
                            if (project != null && !IsValidKzbUrl(studio.Solution, project, nodeResource.ResourceID))
                            {
                                studio.Log($"Invalid kzb URL \"{nodeResource}\" found in the \"{property.DisplayName}\" property of \"{projectItem.Path ?? projectItem.Name}\".");
                                count++;
                            }
                        }
                    }
    
                    count = LogKzbUrls(projectItem, count);
                }
    
                return count;
            }
    
  6. 在实现 PluginCommand 界面的类的 Execute 函数中,写入调用该插件命令时插件执行的代码。
            public void Execute(PluginCommandParameter parameter)
            {
                studio.Log("Finding invalid kzb URLs...");
                //调用打印无效 kzb URL 到 日志 (Log) 的函数。
                var count = LogKzbUrls(studio.ActiveProject, 0);
                studio.Log($"This project contains {count} invalid kzb URLs.");
            }
  7. 构建和运行插件。请参阅构建和运行 Kanzi Studio 插件
    当执行此命令时,插件将无效 kzb URL以及其节点和属性使用无效 kzb URL 的每个 kzb URL 打印到 日志 (Log)

移除无效 kzb URL

要从 Kanzi Studio 工程中移除无效 kzb URL,请执行以下操作:

  1. 实现一个记录无效 kzb URL 的 Kanzi Studio 插件。请参阅 记录无效 kzb URL
  2. 在 Visual Studio 中向您的插件工程添加一个新类,并设置该类以实现 PluginCommand 界面。
    例如,添加一个名为“RemoveInvalidKzbUrls”的类:
    using System.ComponentModel.Composition;
    using Rightware.Kanzi.Studio.PluginInterface;
    
    namespace InvalidKzbUrlFinder
    {
        [Export(typeof(PluginContent))]
        class RemoveInvalidKzbUrls : PluginCommand
        {
            private KanziStudio studio;
    
            public void Initialize(KanziStudio studio)
            {
                this.studio = studio;
            }
    
            //在 Kanzi Studio 主菜单中,显示名为“Kzb URL 检查器”的插件命令。
            public CommandPlacement CommandPlacement =>
                new CommandPlacement("Kzb URL Checker", ContextMenuPlacement.NONE, false, null);
    
            //设置该插件命令的内部名称。此函数使您无需额外更改插件,即可更改命令的显示名称。
            public string Name => "RemoveInvalidKzbUrls";
    
            //设置 Kanzi Studio 主菜单中的命令名。
            public string DisplayName => "Remove Invalid Kzb URLs";
    
            // Set the tooltip for the command.
            public string Description => "Removes the invalid kzb URLs from the active project.";
    
            public bool CanExecute(PluginCommandParameter parameter)
            {
                return studio?.ActiveProject != null;
            }
    
            public void Execute(PluginCommandParameter parameter)
            {
                throw new NotImplementedException();
            }
        }
    }
  3. 在上一步中添加的类中,创建移除无效 kzb URL 的函数。
            private int RemoveKzbUrls(ProjectItem item, int currentCount)
            {
                foreach (var projectItem in item.Children)
                {
                    var properties = projectItem.Properties;
    
                    foreach (var property in properties)
                    {
                        var propertyValue = projectItem.Get(property);
                        var nodeResource = propertyValue as ResourceReferenceBase;
                        if (nodeResource != null)
                        {
                            var project = ListInvalidKzbUrls.GetProjectFromKzbUrl(studio.Solution, nodeResource.ResourceID);
                            if (project != null &&
                                !ListInvalidKzbUrls.IsValidKzbUrl(studio.Solution, project, nodeResource.ResourceID))
                            {
                                projectItem.Set(property.Name, null);
                                currentCount++;
                            }
                        }
                    }
    
                    currentCount = RemoveKzbUrls(projectItem, currentCount);
                }
    
                return currentCount;
            }
  4. Execute 函数中,编写当您调用插件命令时插件执行的代码。
            public void Execute(PluginCommandParameter parameter)
            {
                studio.Log("Removing invalid kzb URLs...");
                //调用移除无效 kzb URL 的函数。
                var removedCount = RemoveKzbUrls(studio.ActiveProject, 0);
                studio.Log($"Removed {removedCount} invalid kzb URLs from the project.");
            }
  5. 构建和运行插件。请参阅构建和运行 Kanzi Studio 插件
    当执行此命令时,该插件移除无效的 kzb URL。

要进一步开发您的 Kanzi Studio 插件,请参阅 Kanzi Studio 插件接口概览Kanzi Studio 插件接口 API 参考

另请参阅

Kanzi Studio 插件接口概览

Kanzi Studio 插件接口 API 参考

创建 Kanzi Studio 窗口插件

安装 Kanzi Studio 插件

调试 Kanzi Studio 插件

Kanzi Studio 插件